package org.eiahe.hr.attendance.service.impl;

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.ehe.common.core.utils.MapstructUtils;
import org.ehe.system.service.IHrEmployeeService;
import org.eiahe.hr.attendance.domain.AttendanceRecord;
import org.eiahe.hr.attendance.domain.bo.AttendanceRecordBo;
import org.eiahe.hr.attendance.domain.vo.AttendanceRecordVo;
import org.eiahe.hr.attendance.mapper.AttendanceRecordMapper;
import org.eiahe.hr.attendance.service.IAttendanceRecordService;
import org.eiahe.hr.attendance.service.IAttendanceAlgorithmService;
import org.ehe.common.mybatis.core.page.PageQuery;
import org.ehe.common.mybatis.core.page.TableDataInfo;
import org.ehe.system.domain.HrEmployee;
import org.ehe.system.mapper.HrEmployeeMapper;
import org.eiahe.hr.filler.EmployeeNameFiller;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 考勤明细Service业务层处理
 *
 * @author zhangnn
 */
@RequiredArgsConstructor
@Service
public class AttendanceRecordServiceImpl implements IAttendanceRecordService {

    private final AttendanceRecordMapper baseMapper;
    private final IHrEmployeeService employeeService;
    private final IAttendanceAlgorithmService attendanceAlgorithmService;
    private final EmployeeNameFiller employeeNameFiller;

    /**
     * 查询考勤明细
     */
    @Override
    public AttendanceRecordVo queryById(Long recordId) {
        AttendanceRecordVo vo = baseMapper.selectVoById(recordId);
        employeeNameFiller.fillEmployeeName(vo,AttendanceRecordVo::getEmployeeNo,AttendanceRecordVo::setEmployeeName);
        return vo;
    }

    /**
     * 查询考勤明细列表
     */
    @Override
    public TableDataInfo<AttendanceRecordVo> queryPageList(AttendanceRecordBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<AttendanceRecord> lqw = buildQueryWrapper(bo);
        Page<AttendanceRecordVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);

        // 填充员工姓名
        employeeNameFiller.fillEmployeeNames(result.getRecords(),
            AttendanceRecordVo::getEmployeeNo,
            AttendanceRecordVo::setEmployeeName);
        return TableDataInfo.build(result);
    }

    /**
     * 查询考勤明细列表
     */
    @Override
    public List<AttendanceRecordVo> queryList(AttendanceRecordBo bo) {
        LambdaQueryWrapper<AttendanceRecord> lqw = buildQueryWrapper(bo);
        List<AttendanceRecordVo> attendanceRecordVos = baseMapper.selectVoList(lqw);
        employeeNameFiller.fillEmployeeNames(attendanceRecordVos,
            AttendanceRecordVo::getEmployeeNo,
            AttendanceRecordVo::setEmployeeName);
        return attendanceRecordVos;
    }

    private LambdaQueryWrapper<AttendanceRecord> buildQueryWrapper(AttendanceRecordBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<AttendanceRecord> lqw = Wrappers.lambdaQuery();
        if (StringUtils.isNotBlank(bo.getEmployeeName())) {
            List<String> employeeNos = employeeService.queryByEmployeeName(bo.getEmployeeName());
            if (CollUtil.isNotEmpty(employeeNos)) {
                lqw.in(AttendanceRecord::getEmployeeNo, employeeNos);
            } else {
                lqw.eq(AttendanceRecord::getEmployeeNo, -1);
            }
        }
        lqw.eq(StringUtils.isNotBlank(bo.getEmployeeNo()), AttendanceRecord::getEmployeeNo, bo.getEmployeeNo());
        lqw.eq(bo.getAttendanceDate() != null, AttendanceRecord::getAttendanceDate, bo.getAttendanceDate());
        lqw.eq(StringUtils.isNotBlank(bo.getClockType()), AttendanceRecord::getClockType, bo.getClockType());
        lqw.eq(StringUtils.isNotBlank(bo.getClockMethod()), AttendanceRecord::getClockMethod, bo.getClockMethod());
        lqw.eq(StringUtils.isNotBlank(bo.getAttendanceStatus()), AttendanceRecord::getAttendanceStatus,
                bo.getAttendanceStatus());
        lqw.eq(StringUtils.isNotBlank(bo.getIsDuplicate()), AttendanceRecord::getIsDuplicate, bo.getIsDuplicate());

        // 日期范围查询
        if (params.get("beginAttendanceDate") != null && params.get("endAttendanceDate") != null) {
            lqw.between(AttendanceRecord::getAttendanceDate,
                    params.get("beginAttendanceDate"), params.get("endAttendanceDate"));
        }

        lqw.orderByDesc(AttendanceRecord::getClockTime);
        return lqw;
    }

    /**
     * 新增考勤明细
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean insertByBo(AttendanceRecordBo bo) {
        AttendanceRecord add = MapstructUtils.convert(bo, AttendanceRecord.class);

        // 调用核心算法处理考勤记录(状态判定、重复打卡处理)
        attendanceAlgorithmService.processAttendanceRecord(add);

        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setRecordId(add.getRecordId());
        }
        return flag;
    }

    /**
     * 修改考勤明细
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean updateByBo(AttendanceRecordBo bo) {
        AttendanceRecord update = MapstructUtils.convert(bo, AttendanceRecord.class);

        // 调用核心算法重新处理考勤记录
        attendanceAlgorithmService.processAttendanceRecord(update);

        return baseMapper.updateById(update) > 0;
    }

    /**
     * 校验并批量删除考勤明细信息
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deleteWithValidByIds(Collection<Long> ids) {
        return baseMapper.deleteByIds(ids) > 0;
    }

    /**
     * 合并重复打卡记录
     * 保留最早的打卡记录,删除重复的
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Integer mergeDuplicateClockRecords(LocalDate date) {
        // 构建查询条件
        LambdaQueryWrapper<AttendanceRecord> lqw = Wrappers.lambdaQuery();
        lqw.eq(AttendanceRecord::getIsDuplicate, "1"); // 只处理标记为重复的记录
        if (date != null) {
            lqw.eq(AttendanceRecord::getAttendanceDate, date);
        }
        lqw.orderByAsc(AttendanceRecord::getEmployeeNo)
                .orderByAsc(AttendanceRecord::getAttendanceDate)
                .orderByAsc(AttendanceRecord::getClockType)
                .orderByAsc(AttendanceRecord::getClockTime);

        List<AttendanceRecord> duplicateRecords = baseMapper.selectList(lqw);
        if (duplicateRecords.isEmpty()) {
            return 0;
        }

        int mergedCount = 0;
        String currentKey = null;
        Long keepRecordId = null;
        List<Long> deleteIds = new ArrayList<>();

        // 按员工+日期+打卡类型分组处理
        for (AttendanceRecord record : duplicateRecords) {
            String key = record.getEmployeeNo() + "_" + record.getAttendanceDate() + "_" + record.getClockType();

            if (!key.equals(currentKey)) {
                // 新的一组,保留第一条(最早的)
                currentKey = key;
                keepRecordId = record.getRecordId();
                // 将保留的记录标记为非重复
                record.setIsDuplicate("0");
                baseMapper.updateById(record);
            } else {
                // 同一组的重复记录,标记为删除
                deleteIds.add(record.getRecordId());
                mergedCount++;
            }
        }

        // 批量删除重复记录
        if (!deleteIds.isEmpty()) {
            baseMapper.deleteByIds(deleteIds);
        }

        return mergedCount;
    }


    /**
     * 查询考勤明细列表
     * 30天内考勤异常
     */
    @Override
    public TableDataInfo<AttendanceRecordVo> listMonth(AttendanceRecordBo bo, PageQuery pageQuery) {
        if(StringUtils.isBlank(bo.getEmployeeNo())){
            return new TableDataInfo<>();
        }
        LambdaQueryWrapper<AttendanceRecord> lqw = new LambdaQueryWrapper<>();
        lqw.eq(AttendanceRecord::getEmployeeNo,bo.getEmployeeNo());
        lqw.ne(AttendanceRecord::getAttendanceStatus,0);//异常
        lqw.between(AttendanceRecord::getAttendanceDate,LocalDate.now().minusDays(30),LocalDate.now());

        Page<AttendanceRecordVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        // 填充员工姓名
        employeeNameFiller.fillEmployeeNames(result.getRecords(),AttendanceRecordVo::getEmployeeNo,AttendanceRecordVo::setEmployeeName);
        return TableDataInfo.build(result);
    }
}
